package ldh.im.fxbase.component;

import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.util.Callback;
import ldh.im.fxbase.cache.SoftId;

import java.util.*;

public class LimitDataListView<T extends SoftId> extends ListView<T> {

    private List<T> dynaList = new LinkedList<T>();
    private ObservableList<T> datas = FXCollections.observableList(dynaList);
//    private WeakHashMap<String, AtomicInteger> weakHashMap = new WeakHashMap<>();
    private Callback<T, Node> cellCallback;
    private Integer limitTotal = 50;

    public LimitDataListView() {
        this.setItems(datas);
        initCellFactory();
        bind();
    }

    public LimitDataListView(int limitTotal) {
        this();
        this.limitTotal = limitTotal;
    }

    public void setCellCallback(Callback<T, Node> cellCallback) {
        this.cellCallback = cellCallback;
    }

    public Callback<T, Node> getCellCallback() {
        return cellCallback;
    }

    public Integer getLimitTotal() {
        return limitTotal;
    }

    public void setLimitTotal(Integer limitTotal) {
        this.limitTotal = limitTotal;
    }

    private void initCellFactory() {
        this.setCellFactory(new WeakListCell(this));
    }

//    private Integer getViewTotal(String id) {
//        AtomicInteger weakNode = weakHashMap.get(id);
//        if (weakNode != null) {
//            return weakNode.get();
//        }
//        return null;
//    }

    private void incrCellView(String id) {
//        AtomicInteger weakAto = weakHashMap.get(id);
//        if (weakAto == null) {
//            weakAto = new AtomicInteger(0);
//            weakHashMap.putIfAbsent(id, weakAto);
//        }
//        weakAto.incrementAndGet();
    }

    private void bind() {
        datas.addListener((ListChangeListener<T>) l->{
            while(l.next()) {
//                for(T t : l.getAddedSubList()) {
//                    weakHashMap.put(t.getSoftId(), new AtomicInteger(0));
//                }
                if (l.getAddedSize() > 0) {
                    removeLimit();
                }
//                for(T t : l.getRemoved()) {
//                    weakHashMap.remove(t.getSoftId());
//                }
            }
        });
    }

    private void removeLimit() {
        if (datas.size() > limitTotal) {
            List<String> removes = new ArrayList();
            int count = datas.size() - limitTotal;
//            Map<String, AtomicInteger> sortMap = MapUtil.sortMapByValue(weakHashMap, (a1, a2)->a1.get()-a2.get());
            for(int i=0; i<count; i++) {
                dynaList.remove(0);
            }
        }
    }


    private class WeakListCell<T extends SoftId> implements Callback<ListView<T>, ListCell<T>> {

        private LimitDataListView<T> limitDataListView;

        public WeakListCell(LimitDataListView<T> limitDataListView) {
            this.limitDataListView = limitDataListView;
        }

        @Override
        public ListCell<T> call(ListView<T> tListView) {
            return new ListCell<T>() {

                @Override
                protected void updateItem(T item, boolean empty) {
                    super.updateItem(item, empty);
                    if (limitDataListView.getCellCallback() == null) throw new RuntimeException("请设置CellCallBack!");
                    if (item == null) {
                        setGraphic(null);
                        setText(null);
                        return;
                    }
                    Node node = newCellData(item, empty);
                    if (node == null) {
                        setGraphic(null);
                        setText(null);
                        return;
                    }
                    String id = item.getSoftId();
                    limitDataListView.incrCellView(id);
                }

                private Node newCellData(T item, boolean empty) {
                    if (item == null || empty) {
                        setGraphic(null);
                        setText(null);
                        return null;
                    } else {
                        Node node = limitDataListView.getCellCallback().call(item);
                        if (node == null) {
                            setGraphic(null);
                            setText(null);
                            return null;
                        }
                        setGraphic(node);
                        setText(null);
                        return node;
                    }
                }
            };

        }
    }



}
